package cn.cloud9.opencloud.common.security;

import cn.cloud9.opencloud.common.util.EmptyUtil;
import cn.cloud9.opencloud.common.util.EncodeUtil;
import lombok.SneakyThrows;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author OnCloud9
 * @description
 * @project Open-Cloud
 * @date 2022年04月16日 21:11
 */
public class XssRequestWrapper extends HttpServletRequestWrapper {

    private String requestBodyString;

    public XssRequestWrapper(HttpServletRequest request, String requestBodyString) {
        super(request);
        this.requestBodyString = requestBodyString;
    }

    @Override
    public String[] getParameterValues(String name) {
        final String[] values = super.getParameterValues(name);
        if (null == values) return values;

        String[] encodeValues = new String[values.length];
        for (int i = 0; i < values.length; i++) encodeValues[i] = EncodeUtil.encodeHTML(values[i]);
        return encodeValues;
    }

    @Override
    public String getHeader(String name) {
        final String header = super.getHeader(name);
        return header == null ? null : EncodeUtil.encodeHTML(header);
    }


    public ServletInputStream getInputStream() {
        if (EmptyUtil.isEmptyString(requestBodyString)) return null;
        final byte[] BYTES = requestBodyString.getBytes(StandardCharsets.UTF_8);

        final ServletInputStream inputStream = new ServletInputStream() {
            private int lastIndexRetrieved = -1;
            private ReadListener readListener = null;

            @Override
            public int read() throws IOException {
                int cursor;
                if (this.isFinished()) return -1;
                cursor = BYTES[lastIndexRetrieved + 1];
                ++ lastIndexRetrieved;
                readListener.onAllDataRead();
                return cursor;
            }

            @Override
            public boolean isFinished() {
                return lastIndexRetrieved == BYTES.length - 1;
            }

            @Override
            public boolean isReady() {
                return this.isFinished();
            }

            @SneakyThrows
            @Override
            public void setReadListener(ReadListener readListener) {
                this.readListener = readListener;
                if (!isFinished()) readListener.onDataAvailable();
                else readListener.onAllDataRead();
            }
        };

        return null;
    }



}
